from django.shortcuts import render
from django.views import View
from django import http
from apps.users.models import User
from django.contrib.auth import login,authenticate,logout
from django_redis import get_redis_connection
from meiduo_all.utils.views import LoginRequiredJSONMixin
import logging,json,re


# 日志输出器
logger = logging.getLogger('django')
# Create your views here.

class UserInfoView(LoginRequiredJSONMixin,View):
    """用户中心
    GET /info/
    """
    def get(self,request):
        """实现用户中心数据展示"""
        data_dict = {
            'code':0,
            'errmsg':'OK',
            'info_data':{
                'username':'',
                'password':'',
                'email':'',
                'email_active':''
            }
        }
        return http.JsonResponse(data_dict)

class LogoutView(View):
    """退出用户登录
    GET /logout/
    """
    def delete(self,request):
        """
        实现退出逻辑
        提示：
            退出逻辑跟登录逻辑相反
            登录成功后是 保持登录状态
            退出登录就是 清除登录状态
        """
        # 清除登录逻辑
        logout(request)

        # 清理用户cookie
        response = http.JsonResponse({'code':0,'errmsg':'退出成功'})
        response.delete_cookie('username')

        return response

class LoginView(View):
    """用户登录
    GET /login/
    """
    def post(self,request):
        """实现用户登录逻辑"""
        # 接受参数
        json_dict = json.loads(request.body.decode())
        # username = json_dict.get('username')
        # 该参数即可是用户名也可是手机号
        account = json_dict.get('username')
        password = json_dict.get('password')
        # 是否记住登录
        remembered = json_dict.get('remembered')

        # 校验参数
        if not all([account,password]):
            return http.JsonResponse({'code':400,'errmsg':'缺少必传参数'})

        # if not re.match(r'^[a-zA-Z0-9_-]{5,20}$',username):
        #     return http.JsonResponse({'code':400,'errmsg':'username格式错误'})

        if not re.match(r'^[a-zA-Z0-9_-]{8,20}$',password):
            return http.JsonResponse({'code':400,'errmsg':'password格式错误'})

        # 实现多账号登录
        # 判断用户输入的是用户名还是手机号
        if re.match(r'^[a-zA-Z0-9_-]{5,20}$', account):
            # 手机号
            User.USERNAME_FIELD = 'mobile'
        else:
            # 用户名
            User.USERNAME_FIELD = 'username'


        # 实现核心逻辑
        # 认证登录用户：Django的用户认证系统已经封装好了
        # 核心思想：先使用用户名作为条件去用户表查询该记录是否存在
        #   如果该用户名存在，再去校验密码是否正确
        # authenticate()仅是证明用户存在并且密码无误
        user = authenticate(request=request,username=account,password=password)
        # user 存在(True) 不存在(False)
        # 判断用户名或密码是否认证成功
        if not user:
            return http.JsonResponse({'code':400,'errmsg':'用户名或密码错误'})


        # 实现状态保持
        login(request,user)
        # 根据remembered参数设置状态保存
        if remembered:
            # 记住登录：保持两周(设置session数据过期时间)
            request.session.set_expiry(None) # None默认2周
        else:
            # 没有记住：浏览器结束就销毁
            request.session.set_expiry(0)

        # 登录后显示用户名
        response = http.JsonResponse({'code':0,'errmsg':'ok'})
        response.set_cookie('username',user.username,max_age=3600*24*14)

        # 响应结果
        return response

class RegisterView(View):
    """
    用户注册
    POST http://www.meiduo.site:8000/register/
    """
    def post(self,request):
        """
        实现注册逻辑
        :param request:
        :return:
        """
        # 接受参数：请求体中的JSON数据 request.body
        json_bytes = request.body # 1.从请求体获取原始的json数据，bytes类型
        json_str = json_bytes.decode() # 2.将bytes类型的json数据，转成json字符串
        json_dict = json.loads(json_str)# 3.将json字符串，转成Python字典
        # json_dict = json.loads(request.body.decode()) 简写

        # 提取参数
        username = json_dict.get('username')
        password = json_dict.get('password')
        password2 = json_dict.get('password2')
        mobile = json_dict.get('mobile')
        allow = json_dict.get('allow')
        sms_code_client = json_dict.get('sms_code')

        # 校验参数
        # 判断是否是必传参数
        # all([]):判断某些数据中是否有为空的数据,只要有一个数据为空，返回false
        if not all([username,password,password2,mobile,allow,sms_code_client]):
            return http.JsonResponse({'code':400,'errmsg':'缺少必传参数'})

        # 判断用户名是否满足格式要求
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}',username):
            # 如果用户名不满足格式要求，返回错误，终止逻辑
            return http.JsonResponse({'code':400,'errmsg':'username有误'})

        # 判断密码是否满足格式要求
        if not re.match(r'^[a-zA-Z0-9_-]{8,20}',password):
            # 如果密码不满足格式要求，返回错误，终止逻辑
            return http.JsonResponse({'code':400,'errmsg':'password有误'})

        # 判断用户两次输入的密码是否一致
        if password != password2:
            return http.JsonResponse({'code':400,'errmsg':'密码不一致'})

        # 判断手机号是否满足格式要求
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400,'errmsg': 'mobile格式有误'})

        # 判断短信验证码是否正确
        # 提取服务端短信验证码
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s'%mobile)

        # 判断短信验证码是否过期
        if not sms_code_server:
            return http.JsonResponse({'code':400,'errmsg':'短信验证码失效'})

        # 对比用户输入和服务端的是否一致
        if sms_code_client != sms_code_server.decode():
            return http.JsonResponse({'code': 400, 'errmsg': '短信验证码不一致'})

        # 判断是否勾选协议
        if allow != True:
            return http.JsonResponse({'code': 400, 'errmsg': 'allow有误'})

        # 实现核心逻辑：保存注册数据到数据表
        # 由于美多商城用户模块完全依赖django自带的用户模型类
        # 所以用户相关的一切操作都需要调用django自带的用户模型类提供的方法和属性
        # 其中就包括了保存用户的注册数据，
        # django自带的用户模型类提供了create_user()专门保存用户注册数据
        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': 400, 'errmsg': '注册失败'})

        # 实现状态保持
        # 记住当前用户登录，session机制
        # login()方法是django提供的用于登录状态保持
        # login('请求对象','')
        login(request,user)

        # 登录后显示用户名
        response = http.JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)

        # 响应结果
        return response


class UsernameCountView(View):
    """判断用户名是否重复注册
    GET http://www.meiduo.site:8000/usernames/itcast/count/
    """
    def get(self,request,username):
        """查询用户名对应记录个数"""

        try:
            count = User.objects.filter(username=username).count()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code':'400','errmsg':'数据错误'})

        return http.JsonResponse({'code': '0', 'errmsg': 'OK', 'count': count})


class MobileCountView(View):
    """判断手机号是否重复"""
    def get(self,request,mobile):
        try:
            count = User.objects.filter(mobile=mobile).count()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code':'400','errmsg':'数据错误'})

        return http.JsonResponse({'code':'0','errmsg':'OK','count':count})
